package com.jmxcfc.blfsc.ssq.service.usersignature.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jmxcfc.blfsc.common.common.enums.ProcessStateEnum;
import com.jmxcfc.blfsc.common.common.request.BaseRequest;
import com.jmxcfc.blfsc.common.common.response.BaseResponse;
import com.jmxcfc.blfsc.common.exception.AfterOutboundException;
import com.jmxcfc.blfsc.common.exception.BeforeOutboundException;
import com.jmxcfc.blfsc.common.exception.OutboundException;
import com.jmxcfc.blfsc.common.sign.SignRequest;
import com.jmxcfc.blfsc.common.sms.BaseContext;
import com.jmxcfc.blfsc.common.validation.rule.RequestFieldRule;
import com.jmxcfc.blfsc.common.validation.rule.SignRulesUtil;
import com.jmxcfc.blfsc.ssq.common.Constants;
import com.jmxcfc.blfsc.ssq.entity.CreateUserSignatureSub;
import com.jmxcfc.blfsc.ssq.modle.response.SsqResponse;
import com.jmxcfc.blfsc.ssq.service.SignatureService;
import com.jmxcfc.blfsc.ssq.service.usersignature.ICreateUserSignatureRequestService;
import com.jmxcfc.blfsc.ssq.service.usersignature.ICreateUserSignatureSubService;
import com.jmxcfc.blfsc.ssq.util.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.List;

/**
 * 功能描述
 * 生成用户签名/印章图片服务类(个人签章的时候需要请求的接口)
 * 请求参数:account(账户,取值身份证号)、text(可不填,系统默认使用证件信息上的名称)
 * @author: pbs
 * @date: 2024年09月04日 0:02
 */
@Service
@Slf4j
public class CreateUserSignatureRequestServiceImpl implements ICreateUserSignatureRequestService {

    //生成用户签名/印章图片请求地址
    @Value("${com.ssq.createUserSignature.url}")
    private String createUserSignatureUrl;

    @Value("${com.ssq.createUserSignature.fontSize}")
    private String fontSize;

    /**
     * 字体名称(仅针对个人类型账号有效)
     */
    @Value("${com.ssq.createUserSignature.fontName}")
    private String fontName;

    /**
     *
     * 字体颜色（仅针对个人类型账号有效）
     */
    @Value("${com.ssq.createUserSignature.fontColor}")
    private String fontColor;

    private SignatureService signatureService;
    private RestTemplate restTemplate;
    private ICreateUserSignatureSubService createUserSignatureSubService;



    @Autowired
    public void setSignatureService(SignatureService signatureService) {
        this.signatureService = signatureService;
    }


    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }


    @Autowired
    public void setCreateUserSignatureSubService(ICreateUserSignatureSubService createUserSignatureSubService) {
        this.createUserSignatureSubService = createUserSignatureSubService;
    }


    @Override
    public BaseResponse<CreateUserSignatureSub> sendRequest(BaseRequest<SignRequest<JSONObject>> requestMessage) {
        BaseContext<String> baseContext = new BaseContext<>();
        //头部参数校验规则:业务号
        List<RequestFieldRule<?>> headerElementRules = baseContext.getHeaderElementRules();
        headerElementRules.add(SignRulesUtil.getRequestNoRule());
        //请求体参数校验:用户账号account(证件号码)
        List<RequestFieldRule<?>> bodyElementRules = baseContext.getBodyElementRules();
        bodyElementRules.add(SignRulesUtil.getIdCodeRule());
        return execute(requestMessage, baseContext);
    }

    /**
     * 1、规则校验业务号
     * 2、参数组织:account(账户,取值身份证号)、text(可不填,系统默认使用证件信息上的名称)
     * @param request
     * @param response
     * @param baseContext
     * @throws BeforeOutboundException
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void beforeOutbound(BaseRequest<SignRequest<JSONObject>> request, BaseResponse<CreateUserSignatureSub> response, BaseContext<String> baseContext) throws BeforeOutboundException {
        String requestNo = request.getHeader().getRequestNo();
        try {
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,前置处理:数据落库和参数组装", requestNo);

            CreateUserSignatureSub createUserSignatureSub = new CreateUserSignatureSub();
            createUserSignatureSub.setRequestNo(requestNo);

            
            //参数组织、queryUserApplyCertSub设置值
            String requestParamStr = buildParam(request, createUserSignatureSub);

            //由于是签名参数追加为url参数:/openapi/v2/signatureImage/user/create?developerId=aaaaaa&rtick=14840209310001&signType=rsa
            String urlPathParams = signatureService.buildUrlPathParams(createUserSignatureUrl, "", requestParamStr);
            //请求路径的url的参数
            baseContext.setExtendStr(urlPathParams);
            //设置请求
            baseContext.setRestHttpEntity(HttpUtils.creatRequestEntity(requestParamStr));
            //保存数据
            createUserSignatureSubService.save(createUserSignatureSub);
            //主键
            baseContext.setRecordId(createUserSignatureSub.getId());
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,前置处理结束", requestNo);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},前置处理异常:{}", requestNo, e.getMessage(), e);
            throw new BeforeOutboundException(e.getMessage(), e);
        }
    }

    @Override
    public void outbound(BaseRequest<SignRequest<JSONObject>> request, BaseResponse<CreateUserSignatureSub> response, BaseContext<String> baseContext) throws OutboundException {
        try{
            //请求url的,必须要用URL,否则restTemplate会对url进行
            URI requestUrl = new URI( StringUtils.join(createUserSignatureUrl, baseContext.getExtendStr()));
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,发送请求外呼,请求地址:{},请参数:{}",request.getHeader().getRequestNo(),requestUrl,baseContext.getRestHttpEntity().getBody());
            String resp = restTemplate.postForObject(requestUrl, baseContext.getRestHttpEntity(), String.class);
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,发送请求外呼,响应内容:{}", request.getHeader().getRequestNo(), resp);
            baseContext.setRestResponse(resp);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},生成用户签名/印章图片 接口,发送请求外呼异常:{}", request.getHeader().getRequestNo(), e.getMessage());
            throw new OutboundException(e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void afterOutbound(BaseRequest<SignRequest<JSONObject>> request, BaseResponse<CreateUserSignatureSub> response, BaseContext<String> baseContext) throws AfterOutboundException {
        String requestNo = request.getHeader().getRequestNo();
        try{
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,后置处理:解析响应结果", requestNo);
            CreateUserSignatureSub createUserSignatureSub = new CreateUserSignatureSub();
            createUserSignatureSub.setRequestNo(requestNo);
            //注意这边是根据主键更新
            createUserSignatureSub.setId(baseContext.getRecordId());
            SsqResponse ssqResponse = JSON.parseObject(baseContext.getRestResponse(),SsqResponse.class);
            //错误码值,0:成功
            String errno = ssqResponse.getErrno();
            //错误信息描述
            String errmsg = ssqResponse.getErrmsg();
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,响应的结果 errno:{},errmsg:{}", requestNo, errno, errmsg);

            if (StringUtils.equals(errno, Constants.ERRNO_0)) {
                response.getHeader().setProcessState(ProcessStateEnum.SUCCESS);
            }else {
                response.getHeader().setProcessState(ProcessStateEnum.FAILURE);
            }
            createUserSignatureSub.setErrno(errno);
            createUserSignatureSub.setErrmsg(errmsg);
            createUserSignatureSubService.updateById(createUserSignatureSub);

            response.getHeader().setResCode(errno);
            response.getHeader().setResMessage(errmsg);
            response.setBody(createUserSignatureSub);
            log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,后置处理结束", requestNo);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},生成用户签名/印章图片 接口,后置处理异常:{}", requestNo, e.getMessage(), e);
            throw new AfterOutboundException(e.getMessage(), e);
        }
    
    }


    /**
     * 参数组织
     * 1、账户必传取值于身份证、字号(目前现有代码是传27)
     * 2、text签名/印章图片上生成的文本字段:可不填,系统默认使用证件信息上的名称【现有代码逻辑是不传】
     * 3、用户签章的一些属性:
     目前只传了fontSize(字号（仅针对个人类型账号有效）),未传:fontName(字体名称（仅针对个人类型账号有效）)、fontColor(字体颜色（仅针对个人类型账号有效）)
     fontSize:字号 20~120，默认30，此参数影响签名字体的清晰度和签名图片大小，字号越高，字体显示越大，清晰度越高
     fontName:字体名称 目前枚举值如下： SimHei 黑体 SimSun 宋体 SimKai 楷体
     fontColor:字体颜色 指定字体的颜色，支持： red（红），black（黑），blue（蓝），purple（紫），grey（灰），brown（棕），tan(褐色)，cyan(青色)
     * @param request
     * @param createUserSignatureSub
     * @return
     */
    private String buildParam(BaseRequest<SignRequest<JSONObject>> request, CreateUserSignatureSub createUserSignatureSub) {
        String requestNo = request.getHeader().getRequestNo();
        JSONObject requestParam = new JSONObject();
        requestParam.put(Constants.ACCOUNT, request.getBody().getIdCode());
        // todo 待确定是否需要传(可不填，系统默认使用证件信息上的名称)
        if (StringUtils.isNotBlank(request.getBody().getAcctName())) {
            requestParam.put(Constants.TEXT, request.getBody().getAcctName());
        }
        //requestParam.put(Constants.TEXT, request.getBody().getAcctName());
        requestParam.put(Constants.FONT_SIZE, fontSize);

        if (StringUtils.isNotBlank(fontSize)) {
            requestParam.put(Constants.FONT_SIZE, fontSize);
        }

        if (StringUtils.isNotBlank(fontName)) {
            requestParam.put(Constants.FONT_NAME, fontName);
        }

        if (StringUtils.isNotBlank(fontColor)) {
            requestParam.put(Constants.FONT_COLOR, fontColor);
        }

        createUserSignatureSub.setAccount(requestParam.getString(Constants.ACCOUNT));
        createUserSignatureSub.setFontSize(requestParam.getString(Constants.FONT_SIZE));
        log.info("请求业务号requestNo:{},生成用户签名/印章图片 接口,参数组织完成,参数:{}", requestNo, JSON.toJSONString(requestParam));
        return JSON.toJSONString(requestParam);
    }


}